"""menus.py - Game menus.
"""

import os
import sys

import pygame
from pygame.locals import *

import data, game, credits, context, fonts


class _Menu(context.Context):
    
    fg_color = Color('darkred')
#    bg_color = Color(139,69,19)  # chocolate4
#    bg_color = Color(93,46,13)  # chocolate4 * 2/3
    bg_color = Color(46,23,6)  # chocolate4 * 1/3

    hi_color = 0xFFFFFF #(white) - we can use webcolours like #FFFFFF as 0xFFFFFF
#    hi_color = Color('white')

    border_color = Color('lightgrey')
    colorkey = Color('black')
    border = 1
    
    def __init__(self, *items):
        """Create a _Menu.
        
        items: A vararg of tuples (text,callback). The callback should require
            no arguments.
        """
        font_file = data.filepath(os.path.join('font','zxumbi.ttf'))
        self.font = pygame.font.Font(font_file, 24)
        
        # Create the list of labels images.
        self.labels = [self._render(text) for text,func in items]
        # Corresponding list of callbacks.
        self.funcs = [func for text,func in items]
        
        # Some useful static values.
        self.nr_items = len(self.labels)
        self.left_align,width,height = self._get_dimensions()
        
        # The menu selector image.
        self.hilight = pygame.surface.Surface((width,height))
        self.hilight.fill(self.colorkey)
        self.hilight.set_colorkey(self.colorkey)
        pygame.draw.rect(self.hilight, self.hi_color, Rect(0,0,width,height), 1)
        
        # The index of the currently selected item.
        self.selected = 0
    
    def _get_dimensions(self):
        """Return the tuple (left,width,height) where left is the left edge of
        alignment, and width and height are the dimensions of the largest label.
        """
        screen_rect = pygame.display.get_surface().get_rect()
        centerx = screen_rect.centerx
        left = screen_rect.centerx
        width = 0
        # Find the widest label and calculate its left edge for alignment.
        for label in self.labels:
            rect = label.get_rect()
            x = centerx - rect.width // 2
            left = min(left, x)
            width = max(width, rect.width)
        # Adjust for text border.
        width += self.border * 2
        height = self.font.get_height() + self.border * 2
        left -= self.border
        return left,width,height
    
    def _render(self, text):
        """Write bordered text to a surface.
        """
        return fonts.render_with_border(
            text, self.font, self.fg_color, self.bg_color, self.border_color,
            self.border
        )

    
    def think(self):
        self.draw()
        self.get_input()
    
    def draw(self):
        screen = pygame.display.get_surface()
        screen_rect = screen.get_rect()
        nr_items = self.nr_items
        font_height = self.font.get_height()
        
        screen.fill(self.bg_color)
        top = screen_rect.centery - font_height * nr_items//2
        bottom = top+nr_items*font_height
        step = font_height
        for i,y in enumerate(range(top, bottom, step)):
            pos = (self.left_align, y)
            label = self.labels[i]
            screen.blit(label, pos)
            if self.selected == i:
                screen.blit(self.hilight, pos)
        pygame.display.flip()
    
    def get_input(self):
        for e in pygame.event.get():
            if e.type == QUIT:
                context.pop()
            elif e.type == KEYDOWN:
                if e.key == K_UP:
                    if self.selected > 0:
                        self.selected -= 1
                elif e.key == K_DOWN:
                    if self.selected < self.nr_items - 1:
                        self.selected += 1
                elif e.key == K_ESCAPE:
                    context.pop()
                elif e.key == K_RETURN:
                    run_func = self.funcs[self.selected]
                    run_func()


class MainMenu(_Menu):
    
    def __init__(self):
        super(MainMenu, self).__init__(
            ('Start Level 1', lambda: context.push(game.GameContext('level-1.tmx'))),
            ('Start minix', lambda: context.push(game.GameContext('mini2.tmx'))),
            ('Quit', context.pop),
            ('Credits', lambda: context.push(credits.CreditsContext())),
        )

class PauseMenu(_Menu):
    
    def __init__(self):
        super(PauseMenu, self).__init__(
            ('Resume', context.pop),
            ('Quit to menu', lambda: context.pop(2)),
        )


